package etxt2db.minorthird;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import edu.cmu.minorthird.text.MonotonicTextLabels;
import edu.cmu.minorthird.text.NestedTextLabels;
import edu.cmu.minorthird.text.Span;
import edu.cmu.minorthird.text.TextLabels;
import edu.cmu.minorthird.text.mixup.Mixup;
import edu.cmu.minorthird.text.mixup.MixupInterpreter;
import edu.cmu.minorthird.text.mixup.MixupProgram;


public class MultiClassInsideOutsideReduction extends
		MultiClassExtraction2TaggingReduction implements Serializable{
	private static final long serialVersionUID=1;

	// saves result of last reduction
	transient private NestedTextLabels taggedLabels;

	private Set<String> tokenProps = new HashSet<String>();

	// all tag values that were used
	private Set<String> tagset=new HashSet<String>();

	public void reduceExtraction2Tagging(MultiClassAnnotationExample example){
		reduceDocument(example.getDocumentSpan(),example.getLabels(),example.getInputTypes());
	}

	private void reduceDocument(Span doc,TextLabels labels,List<String> spanTypes){
		taggedLabels=new NestedTextLabels(labels);
		tokenProps.addAll(spanTypes);
		for(String spanType : tokenProps) {
			assignDefaultLabels(doc,taggedLabels,spanType);
			// label the tokens inside a span to be extracted as POS, if there's just
			// one
			// type to extract, or with the property value, otherwise.
			String id=doc.getDocumentId();
			Iterator<Span> i= taggedLabels.instanceIterator(spanType,id);
			while(i.hasNext()){
				Span span=i.next();
				String tag=spanType;
				tagset.add(tag);
				for(int j=0;j<span.size();j++){
					taggedLabels.setProperty(span.getToken(j),spanType,tag);
				}
			}
		}
	}

	public List<String> getTokenProp(){
		return new ArrayList<String>(tokenProps);
	}

	public Set<String> getNonDefaultTagValues(){
		return tagset;
	}

	public TextLabels getTaggedLabels(){
		return taggedLabels;
	}

	/**
	 * Return a TextLabels in which tagged tokens are used to solve the extraction
	 * problem.
	 */
	public void extractFromTags(List<String> output,MonotonicTextLabels taggedLabels){
		try{
			MixupProgram p=new MixupProgram();
			for(String type : output){
				p.addStatement("defSpanType "+type+" =: "+
							makePattern(type,type));
			}
			MixupInterpreter interp=new MixupInterpreter(p);
			interp.eval(taggedLabels);
		}catch(Mixup.ParseException ex){
			throw new IllegalStateException("mixup error: "+ex);
		}
	}

	private String makePattern(String val,String prop){
		return "... [L "+prop+":"+val+"+ R] ...";
	}
}
